package 反射;
/*
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Member;

Executable类从字面意思上来理解是可执行的意思，其下由两个子类Method和Constructor。

声明的方法:
方法	                           说明
getParameterTypes()	           按照声明顺序返回 Class 对象的数组，这些对象描述了此 Method/Constructor 对象所表示的方法的形参类型。
getExceptionTypes()	           返回 Class 对象的数组，这些对象描述了声明将此 Method/Constructor 对象表示的底层方法抛出的异常类型。
getGenericParameterTypes()	     按照声明顺序返回 Type 对象的数组，这些对象描述了此 Method/Constructor 对象所表示的形参类型的。
getGenericExceptionTypes()	     返回 Type 对象数组，这些对象描述了声明由此 Method/Constructor 对象抛出的异常的类型。
toGenericString()	              返回描述此 Method/Constructor 的字符串，包括类型参数。
getParameterAnnotations()	     返回表示按照声明顺序对此 Method/Constructor 对象所表示方法的形参进行注释的那个数组的数组。
getAnnotatedReturnType()	     返回一个AnnotatedType对象，该对象表示使用一个类型来指定由该可执行文件表示的方法/构造函数的返回类型
getAnnotatedExceptionTypes()    返回一个AnnotatedType对象数组，这些对象表示使用类型来指定由该可执行文件表示的方法/构造函数声明的异常
getAnnotatedReceiverType()	     返回一个AnnotatedType对象，该对象表示使用一个类型来指定该可执行对象表示的方法/构造函数的接收者类型
getAnnotatedParameterTypes()    返回一个AnnotatedType对象数组，这些对象表示使用类型来指定由该可执行文件表示的方法/构造函数的形式参数类型
getParameterCount()	           获取参数的个数（无论是显式声明的还是隐式声明的或不声明的）
getParameters()	              返回一个参数对象数组，该数组表示该方法对象的所有参数
isVarArgs()	                    是否是可变参数


一、Executable类
抽象类Executable 位于包java.lang.reflect中，它是Method和Constructor共享超类，提供了许多展示方法信息的函数。

public abstract class Executable extends AccessibleObject implements Member, GenericDeclaration

●继承了AccessibleObject 类
●实现了Member,GenericDeclaration 接口

其中，AccessibleObject与GenericDeclaration在上篇文章中简单的了解过了，而接口Member却是一个新伙伴。

二、AccessibleObject
public class AccessibleObject extends Object implements AnnotatedElement

AccessibleObject 类实现了AnnotatedElement，它是 Field、Method 和 Constructor 对象的基类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问
控制检查的能力。对于公共成员、默认（打包）访问成员、受保护成员和私有成员，在分别使用 Field、Method 或 Constructor 对象来设置或获得字段、调用方法，或者创建和初
始化类的新实例的时候，会执行访问检查。

1.AccessibleObject的方法：

●isAccessible： public boolean isAccessible()获得此对象的 accessible 标志的值。 Deprecated
此对象的返回值，就是accessible的标志值，一般情况下无论 public，private,protected,默认等修饰的属性的access值均为false（注意他的意思并非是访问权限而是对该自
己执行安全检查）。

●canAccess：public final boolean canAccess(Object obj)
测试调用者是否可以访问此反射对象。
如果此反射对象对应于实例方法或字段，则此方法测试调用者是否可以使用反射对象访问给定的obj。对于实例方法或字段则obj参数必须是实例declaring class。 对
于静态成员和构造函数，则obj必须为null 。
如果accessible标志设置为true ，则此方法返回true ，即抑制Java语言访问控制的检查，或者如果调用者可以访问The Java™ Language Specification中指
定的成员，并且类描述中记录了变体。

参数：obj - 此反射对象的声明类的实例对象（如果它是实例方法或字段）
结果：true如果调用者可以访问此反射对象。
异常：
IllegalArgumentException -
    如果此反射对象是静态成员或构造函数，并且给定的obj是非null ，或者
    如果此反射对象是实例方法或字段，并且给定的obj是null或者类型不是该成员的declaring class的子类。

●setAccessible：
1)public void setAccessible​(boolean flag) 将此反射对象的 accessible标志设置为指示的布尔值。
2)public static void setAccessible​(AccessibleObject[] array, boolean flag) 通过单个安全检查为效率设置反射对象数组的accessible标志的便捷方法（为了提高效率）。

1):
将此反射对象的accessible标志设置为指示的布尔值。 值true表示反射对象在使用时应禁止检查Java语言访问控制。值false表示反射对象在使用时应强制检查Java语
言访问控制，并在类描述中注明变体。
类C的调用者可以使用此方法来访问member的declaring class D如果满足以下任何条件：

◾C和D在同一模块中。
◾该成员是public和D是public在一个包中，该模块包含D 输出至少包含C的模块。
◾所述构件是protected static ， D是public在于包含模块的封装D出口到至少包含模块C ，和C是的一个子类D 。
◾D在一个包中，该模块包含D opens至少包含C的模块。 未命名和打开模块中的所有软件包都对所有模块开放，因此当D位于未命名或打开的模块中时，此方法始终成功。
当声明类与调用者位于不同的模块且包含声明类的包未打开时，此方法不能用于启用对私有成员，具有默认（包）访问的成员，受保护的实例成员或受保护的构造函数的访问来
电者的模块。

如果有安全管理器，则首先使用ReflectPermission("suppressAccessChecks")权限调用其checkPermission方法。

参数:flag - accessible标志的新值
异常:
   InaccessibleObjectException - 如果无法启用访问权限
   SecurityException - 如果安全管理器拒绝请求

2):
通过单个安全检查为效率设置反射对象数组的accessible标志的便捷方法（为了提高效率）。
当可以按照setAccessible(boolean)的规定启用对每个反射对象的访问时，此方法可用于访问阵列中的所有反射对象。

如果有安全管理器，则首先使用ReflectPermission("suppressAccessChecks")权限调用其checkPermission方法。

甲SecurityException如果任何输入的元件的也被抛出array是构造器对象为类java.lang.Class和flag是真实的。

参数: array - AccessibleObjects数组
     flag - 每个对象中 accessible标志的新值
异常:
   InaccessibleObjectException - 如果无法为阵列中的所有对象启用访问权限
   SecurityException - 如果安全管理器拒绝请求，或者数组中的元素是 java.lang.Class的构造 java.lang.Class

●getAnnotation
　　public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
如果存在该元素的指定类型的注释，则返回这些注释，否则返回 null。 
指定者：接口 AnnotatedElement 中的 getAnnotation 　　
参数： annotationClass - 对应于注释类型的 Class 对象 　　
返回：如果该元素的指定注释类型的注释存在于此对象上，则返回这些注释，否则返回 null

参数类型:T - 要查询的注释的类型，如果存在则返回
参数: annotationClass - 与注释类型对应的Class对象
结果: 如果此元素上存在指定注释类型，则此元素的注释，否则为null

●isAnnotationPresent
　　public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
从接口 AnnotatedElement 复制的描述 ,如果指定类型的注释存在于此元素上，则返回 true，否则返回 false。此方法主要是为了便于访问标记注释而设计的。
指定者：接口 AnnotatedElement 中的 isAnnotationPresent 　　
参数：annotationClass - 对应于注释类型的 Class 对象 　　
返回：如果指定注释类型的注释存在于此对象上，则返回 true，否则返回 false

●getAnnotation
　　public Annotation[] getAnnotations()
返回此元素上存在的所有注释。（如果此元素没有注释，则返回长度为零的数组。）该方法的调用方可以随意修改返回的数组；这不会对其他调用方返回的数组产生任何影响。 　　指定者：接口 AnnotatedElement 中的 getAnnotations 　　
返回： 此元素上存在的所有注释

●getDeclaredAnnotation
　　public Annotation[] getDeclaredAnnotations()从接口 AnnotatedElement 复制的描述 　　
返回直接存在于此元素上的所有注释。与此接口中的其他方法不同，该方法将忽略继承的注释。（如果没有注释直接存在于此元素上，则返回长度为零的一个数组。）该方法的调
用方可以随意修改返回的数组；这不会对其他调用方返回的数组产生任何影响。 　　
指定者： 接口 AnnotatedElement 中的 getDeclaredAnnotations 　　
返回： 直接存在于此元素上的所有注释

参数类型:T - 要查询的注释的类型，如果直接或间接存在则返回
参数:annotationClass - 与注释类型对应的Class对象
结果:如果直接或间接出现在此元素上，则指定注释类型的所有此元素的注释，否则为长度为零的数组

我创建了一个Student的model:
*/
//import java.lang.reflect.AccessibleObject;
/*
import java.lang.reflect.Field;
class Studentb {
	private String name;
	private String no;
	public String nickname;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getNo() {
		return no;
	}
	public void setNo(String no) {
		this.no = no;
	}
	public String getNickname() {
		return nickname;
	}
	public void setNickname(String nickname) {
		this.nickname = nickname;
	}
}

public class Executable类 {
	public static void main(String[] args) throws Exception{
		Studentb stu=new Studentb();
		stu.setName("gzq");
		stu.setNickname("jiu ge");
		stu.setNo("100901016");

		Field field=stu.getClass().getDeclaredField("name");//getDeclaredField()可访问private、protected修饰的字段
		
		System.out.println(field.canAccess(stu));//false
		//access flag为false时，字段不可赋值。
		//field.set(stu, "九哥");//出错
		
		field.setAccessible(true);//设置access flag为true
		System.out.println(field.canAccess(stu));//true
		
		//access flag 为true,可赋值至字段private String name
		field.set(stu, "九哥");
		System.out.println("field.get(stu):"+field.get(stu));
		
		Field field1=stu.getClass().getField("nickname");//getField()不可访问private、protected修饰的字段，getDeclaredField则可访问
		System.out.println(field1.canAccess(stu));
		field.setAccessible(false);//不可置public、protected为false
		System.out.println(field1.canAccess(stu));

	}
}
*/

/*
三、Member接口
Member接口也是位于reflect包中.

定义的常量如下：
  ●static int	DECLARED	 标识类或接口的已声明成员集。
  ●static int	PUBLIC	     标识类或接口的所有公共成员的集合，包括继承的成员。

具有以下几个需要实现的方法：
  ●类<?> getDeclaringClass：返回表示类或接口的 Class 对象，该类或接口声明了此 Member 表示的成员或构造函数
  ●int getModifiers：以整数形式返回此 Member 表示的成员或构造函数的 Java 语言修饰符
  ●String getName：返回由该成员表示的底层成员或构造函数的简单名称
  ●boolean isSynthetic：由编译器引入的返回true，否则返回false

终上所述，Member接口规定了实现或继承该接口的类或接口的构造函数、修饰符、名称以及来源。

四、java.lang.reflect.Modifier
Modifier类在Executable中有所涉及，所以需要简单了解一下。
该类提供static方法和常量来解码类和成员访问修饰符。修饰符集表示为整数，具有代表不同修饰符的不同位位置。 表示修饰符的常量的值取
自The Java™ Virtual Machine Specification的第 4.1、4.4、4.5和 4.7 节中的表格。
修饰符列表
public static final int PUBLIC  = 0x00000001;//0000 0000 0000 0001
public static final int PRIVATE  = 0x00000002;//0000 0000 0000 0010
public static final int PROTECTED  = 0x00000004;//0000 0000 0000 0100
public static final int STATIC  = 0x00000008;//0000 0000 0000 1000
public static final int FINAL  = 0x00000010;//0000 0000 0001 0000
public static final int SYNCHRONIZED  = 0x00000020; 同步  //0000 0000 0010 0000
public static final int VOLATILE  = 0x00000040; 用volatile修饰的变量，线程在每次使用变量的时候，都会读取变量修改后的最的值。//0000 0000 0100 0000
public static final int TRANSIENT  = 0x00000080;     用transient关键字标记的成员变量不参与序列化过程。  //0000 0000 1000 0000
public static final int NATIVE  = 0x00000100;  //0000 0001 0000 0000
public static final int INTERFACE  = 0x00000200;//0000 0010 0000 0000
public static final int ABSTRACT  = 0x00000400;//0000 0100 0000 0000
public static final int STRICT  = 0x00000800; 即strictfp(strict float point 精确浮点)，此关键字可应用于类、接口或方法。//0000 1000 0000 0000

解码方法
以上所有的修饰符都有对应的、方法声明为【public static boolean is***(int mod)】的解码方法，且方法的实现也都是类似的，比如：

public static boolean isPublic(int mod) {
    return (mod & PUBLIC) != 0;  //mod=0000 0000 0000 0001(只要最低位为1)  PUBLIC=0000 0000 0000 0001
}

【公开基础修饰符】：
●ACCESS_MODIFIERS 表示访问控制修饰符
  ◾PUBLIC 公开的
  ◾PRIVATE 私有的
  ◾PROTECTED 受保护的

●FINAL 最终的、不允许修改
●INTERFACE 表示接口
●NATIVE 本地
●STATIC 静态
●STRICT 表示strictfp修饰符
●TRANSIENT 临时
●VOLATILE 表示volatile修饰符
●SYNCHRONIZED 同步
●ABSTRACT 表示抽象

【非公开的几个修饰符】：
●BRIDGE
●VARARGS
●ANNOTATION 表示注解
●ENUM
●MANDATED
●SYNTHETIC

【修饰符分类】：
●CLASS_MODIFIERS 可应用于类的 Java 源代码修饰符

  ◾ACCESS_MODIFIERS
  ◾ABSTRACT
  ◾STATIC
  ◾FINAL
  ◾STRICT


●INTERFACE_MODIFIERS 可应用于接口的修饰符，可以看到接口比类就少了一个FINAL,因为它待实现

  ◾ACCESS_MODIFIERS
  ◾ABSTRACT
  ◾STATIC
  ◾STRICT


●CONSTRUCTOR_MODIFIERS 可应用于构造器的修饰符

  ◾ACCESS_MODIFIERS


●METHOD_MODIFIERS 可应用于方法的修饰符

  ◾ACCESS_MODIFIERS
  ◾ABSTRACT
  ◾STATIC
  ◾FINAL
  ◾STRICT
  ◾NATIVE


●FIELD_MODIFIERS 可应用于字段的修饰符

  ◾ACCESS_MODIFIERS
  ◾STATIC
  ◾FINAL
  ◾TRANSIENT
  ◾VOLATILE


●PARAMETER_MODIFIERS 可应用于方法或构造函数参数的 Java 源代码修饰符

  ◾FINAL


从Modifier类的字段定义，我们可以一窥Java的底层风采。
在这些字段中，存在一个很少见的修饰符表示字段，那就是strictfp修饰符的表示字段STRICT。通过使用该字段，我们可以确保浮点计算独立于平台，浮点精度不由系统随意决定。

使用 strictfp 关键字声明一个方法时，该方法中所有的float和double表达式都严格遵守FP-strict的限制,符合IEEE-754规范。当对一个类或接口使用 strictfp 关键字时，
该类中的所有代码，包括嵌套类型中的初始设定值和代码，都将严格地进行计算。

五、Executable的方法
【接口方法】
Executable类实现了以下是几个接口的方法，都没有具体的实现，应该是留给子类实现的。这种方式是名为模版模式的设计模式，便于在不同的子类中可以实现不同务逻辑。

●Member（接口）

  ◾getModifiers
  ◾getName
  ◾getDeclaringClass
  ◾isSynthetic


●GenericDeclaration（接口）

  ◾getTypeParameters
  ◾AnnotatedElement(父接口)

    ◽getAnnotation
    ◽getAnnotations
    ◽getAnnotationsByType
    ◽getDeclaredAnnotation
    ◽getDeclaredAnnotations
    ◽getDeclaredAnnotationsByType
    ◽isAnnotationPresent

模板方法模式定义了一个算法的步骤，并允许子类别为一个或多个步骤提供其实践方式。让子类在不改变算法架构的情况下，重新定义算法中的某些步骤。在软件工程中，它是一种软件设计
模式，和C++模板没有关连。

【其他方法】
1. equalParamTypes
equalParamTypes方法用于比较两组参数的类，按照该逻辑应该是比较方法参数。
boolean equalParamTypes(Class<?>[] params1, Class<?>[] params2) {
    //Avoid unnecessary cloning
    if (params1.length == params2.length) {
        for (int i = 0; i < params1.length; i++) {
            if (params1[i] != params2[i])
                return false;
        }
        return true;
    }
    return false;
}

2. parseParameterAnnotations
parseParameterAnnotations方法用于从比特数组读取注解，可以看到调用了getDeclaringClass方法获取直接注解，作为参数传递
到JavaLangAccess类的getConstantPool 方法中。
Annotation[][] parseParameterAnnotations(byte[] parameterAnnotations) {
    return AnnotationParser.parseParameterAnnotations(
           parameterAnnotations,
           sun.misc.SharedSecrets.getJavaLangAccess().
           getConstantPool(getDeclaringClass()),
           getDeclaringClass());
}

JavaLangAccess是一个接口，存在getConstantPool方法的匿名实现，实际上调用的是一个native方法。
public sun.reflect.ConstantPool getConstantPool(Class<?> klass) {
    return klass.getConstantPool();
}

3. sharedToString
sharedToString方法用于将描述符转换为字符串，打印的数据来自于传入的参数。可以看到存在四个参数：

  ◾modifierMask 表示java.lang.reflect.Modifier类的整形表示
  ◾isDefault 表示是否是接口的默认方法
  ◾parameterTypes 表示参数类型的数组
  ◾exceptionTypes 表示异常类型的数组

相关源码如下：
String sharedToString(int modifierMask,
                      boolean isDefault,
                      Class<?>[] parameterTypes,
                      Class<?>[] exceptionTypes) {
    try {
        StringBuilder sb = new StringBuilder();

        printModifiersIfNonzero(sb, modifierMask, isDefault);
        specificToStringHeader(sb);

        sb.append('(');
        separateWithCommas(parameterTypes, sb);
        sb.append(')');
        if (exceptionTypes.length > 0) {
            sb.append(" throws ");
            separateWithCommas(exceptionTypes, sb);
        }
        return sb.toString();
    } catch (Exception e) {
        return "<" + e + ">";
    }
}

void printModifiersIfNonzero(StringBuilder sb, int mask, boolean isDefault) {
    int mod = getModifiers() & mask;

    if (mod != 0 && !isDefault) {
        sb.append(Modifier.toString(mod)).append(' ');
    } else {
        int access_mod = mod & Modifier.ACCESS_MODIFIERS;
        if (access_mod != 0)
            sb.append(Modifier.toString(access_mod)).append(' ');
        if (isDefault)
            sb.append("default ");
        mod = (mod & ~Modifier.ACCESS_MODIFIERS);
        if (mod != 0)
            sb.append(Modifier.toString(mod)).append(' ');
    }
}

void separateWithCommas(Class<?>[] types, StringBuilder sb) {
    for (int j = 0; j < types.length; j++) {
        sb.append(types[j].getTypeName());
        if (j < (types.length - 1))
            sb.append(",");
    }

}

●printModifiersIfNonzero方法用于打印描述符，当调用方法的modifierMask与当前类的描述符一致或者是默认方法。

  ◾当修饰符一致且非默认方法，打印描述符的字符串表示；
  ◾当修饰符不一致

    ◽存在访问控制修饰符，则打印；
    ◽如果是默认方法，则追加default字符串；
    ◽如果存放非访问控制修饰符，则打印对应的修饰符，

●然后使用specificToStringHeader生成特定于方法或构造函数的 toString 标头信息；

●使用separateWithCommas方法打印所有参数的完整类名；

●如果存在异常类，则调用separateWithCommas方法打印所有异常类的完整类名。

4. 其他信息展示方法
在类Executable中还存在其他展示方法信息的方法：


●sharedToGenericString 生成泛型对象相关字符串

  ◾getTypeParameters 按声明顺序返回一个TypeVariable对象数组，这些对象表示由此对象表示的泛型声明所声明的类型变量
  ◾specificToGenericStringHeader 生成特定于方法或构造函数的 toGenericString 标头信息
  ◾getGenericParameterTypes 返回一个Type对象数组，这些对象按声明顺序表示由此对象表示的可执行文件的形式参数类型
  ◾getGenericExceptionTypes 返回一个Type对象数组，这些对象表示声明为由此可执行对象抛出的异常。如果底层可执行文件在其throws子句中没有声明任何异常，则返回长度为 0 的数组

●getName 返回由此对象表示的可执行文件的名称

●getModifiers 返回此对象表示的可执行文件的 Java 语言修饰符

●getParameters 返回一个Parameter对象数组，这些对象表示此对象表示的底层可执行文件的所有参数

●getAllGenericParameterTypes 行为类似于getGenericParameterTypes ，但返回所有参数的类型信息，包括合成参数。

四、总结
类Executable可以获取注解、修饰符等信息；为Method以及Constructor提供了一个信息输出通道
*/

